<?php

namespace app\common\model;

use app\common\interfaces\RevokeOrder;
use app\common\model\marketing\UsersMarketingCoupons;
use think\Db;
use think\Exception;
use think\Model;
use traits\model\SoftDelete;
use think\Config as SysConfig;
use EasyWeChat\Foundation\Application;
use addons\wechat\library\Config as ConfigService;

class Order extends Model implements RevokeOrder
{
    use SoftDelete;

    protected $deleteTime = 'delete_time';
    // 表名
    protected $name = 'order';
    protected $pk = 'id';
    protected $autoWriteTimestamp = true;
    // 定义时间戳字段名
    protected $createTime = 'add_time';
    protected $updateTime = 'update_time';
    protected $confirm_stock = 0;

    const PAY_STATUS_NO             = 0;              //未付款
    const PAY_STATUS_YES            = 1;              //已付款
    const PAY_STATUS_PARTIAL_REFUND = 2;              //部分退款
    const PAY_STATUS_REFUNDED       = 3;              //已退款
    const USE_STATUS_NO             = 0;              //未使用
    const USE_STATUS                = 1;              //已使用
    const USE_STATUS_OFF            = 2;              //取消
    const USE_STATUS_EXPIRE         = 3;              //已过期
    const USE_STATUS_OVER           = 4;              //订单已完结
    const USE_STATUS_REVOKE         = 5;              //订单撤销
    const USE_STATUS_PARTIAL        = 6;              //部分使用
    const NO_COMMENT                = 0;              //没有评价
    const ALREADY_COMMENT           = 1;              //已经评价
    const ROLE_STORE                = 1;              //购买角色商家
    const ROLE_DIS                  = 2;              //购买角色分销商
    const ROLE_USER                 = 3;              //购买角色普通用户
    const REFUND_MARK_N0            = 0;              //无退款
    const REFUND_MARK_PARTIAL       = 1;              //存在退款
    const REFUND_MARK_YES           = 2;              //全部退款
    const ORDER_CAT_STORE           = 1;              //供应商小店
    const ORDER_CAT_DIST            = 2;              //分销商小店

    public function getIsConfirm()
    {
        return $this->confirm_stock;
    }

    //订单使用状态
    public function getOrderStatusList()
    {
        return [
            '0' => __('Status 0'),
            '1' => __('Status 1'),
            '2' => __('Status 2'),
            '3' => __('Status 3'),
            '4' => __('Status 4'),
            '5' => __('Status 5'),
            '6' => __('Status 6')
        ];
    }


    //修改器,游玩日期备注
    public function setPlayTimeNotesAttr($value,$data)
    {
        $value = $value ? (is_numeric($value) ? date('Y-m-d',$value) : $value )  : date('Y-m-d',$data['play_time']);

        $goods = Goods::get($data['goods_id']);
        if ($goods['deadlineType'] == goods::DEADLINETYPE_2){
            $valid_period_start = datetime($goods['valid_period_start'],'Y-m-d');
            $valid_period_end = datetime($goods['valid_period_end'],'Y-m-d');
            // $week_list =  $goods->getWeekList();
            // $valid_week = $goods->getValidPeriodWeekTextAttr('',$goods);
            // $value = $valid_period_start.'至'.$valid_period_end.($valid_week ? '可用时间:'.$valid_week : '');
            $value = $valid_period_start.'至'.$valid_period_end;
        }elseif ($goods['deadlineType'] == goods::DEADLINETYPE_1){
            $front = $goods['deadlineFront'];
            $later = $goods['deadlineLater'];

            $front_time = strtotime("- $front day",$data['play_time']);//游玩前x天
            $later_time = strtotime("+ $later day",$data['play_time']);//游玩后x天

            $front_time = date('Y-m-d',$front_time);
            $later_time = date('Y-m-d',$later_time);

            if ($front && $later){
                $value = $front_time.'至'.$later_time;
            }elseif ($front){
                $value = $front_time.'至'.$value;
            }elseif($later){
                $value = $value.'至'.$later_time;
            }

        }
        return $value;
    }

    /**
     * @return \think\model\relation\BelongsTo
     * 关联景区表
     */
    public function scenic()
    {
        return $this->belongsTo('Scenic', 'scenic_id')->setEagerlyType(0);
    }
    /**
     * 关联凭证表
     */
    public function voucher()
    {
        return $this->hasMany('Voucher', 'order_id')
            ->order('use_status asc')
            ->field('id,voucher_number,order_id,user_id,status,buynum,consum,no_check_num,use_status,check_time');
    }

    /**
     * 关联凭证记录表
     */
    public function voucherlog()
    {
        return $this->hasMany('Voucherlog', 'order_id')
            ->order('add_time asc')
            ->field('id,voucher_id,voucher_num,order_id,scenic_id,goods_id,store_id,user_id,devices_id,is_thirdparty,add_time');
    }

    /**
     * @return \think\model\relation\HasMany
     * 关联游人信息表
     */
    public function tourist()
    {
        return $this->hasMany(Tourist::class, 'order_id')->field('id,username,phone,id_no,school,student_id,user_id,order_id');
    }
    /***
     * @return \think\model\relation\BelongsTo
     * 关联商品表
     */
    public function goods()
    {
        return $this->belongsTo('app\store\model\Goods', 'goods_id')->setEagerlyType(0);
    }

    /***
     * @return \think\model\relation\BelongsTo
     * 关联供应商表
     */
    public function store()
    {
        return $this->belongsTo('Store', 'store_id')->field('id,store_name,mobile,avatar')->setEagerlyType(1);
    }

    /***
     * @return \think\model\relation\HasMany
     * 关联订单变更记录
     */
    public function orderLog()
    {
        return $this->hasMany('OrderLog', 'order_id');
    }

    /***
     * @return \think\model\relation\HasOne
     * 退款表
     */
    public function refund()
    {
        return $this->hasOne('Refund', 'order_id')->where('refund_status', 'neq', 3)->field('id,order_id,refund_status');
    }

    /***
     * @param array $value
     * @param int $tourists
     * @return array
     * 订单中的联系人信息
     */
    public function setContact(array  $value)
    {

        if (isset($value['contact'])){
            $params = [
                'name'    => $value['contact']['name'],
                'phone'   => $value['contact']['phone'],
                'id_card' => isset($value['contact']['idCard']) ? $value['contact']['idCard'] : '',
                'school'  => isset($value['contact']['schoolName']) ? $value['contact']['schoolName'] : '',
                'student' => isset($value['contact']['studentId']) ? $value['contact']['studentId'] : '',
            ];
        }else{
            $params = [
                'name'    => '',
                'phone'   => '',
                'id_card' => '',
                'school'  => '',
                'student' =>  '',
            ];
        }

        return $params;
    }

    /**
     * @param $order_id 订单id
     * @param  $num 退票数量
     * @throws Exception
     * 撤销订单改变订单状态(退款)
     */
    public function revokeOrder($order_id, $num)
    {

        $orderGoods = new OrderGoods();
        $voucher    = new Voucher();
        $orderLog   = new OrderLog();
        $order      = $this->with(['goods'])
            ->where('order.id', $order_id)
            ->find();
        if ($order['goods']['refundPart']) {
            //整批退完\
            $param = [
                'order_status' => self::USE_STATUS_REVOKE, //撤销（退款）状态
                'refund_mark'  => self::REFUND_MARK_YES, //全退标识
            ];
        } else {
            //分批退款
            //第三方未出票
            if ($order['is_third']) {
                $order_goods = Db::name('order_goods')->where(['order_id'=>$order['id']])->find();
                if ($order_goods) {
                   $use_count_no = OrderGoods::where(['order_id' => $order_id, 'status' => 0])->count(); //未使用的票数
                }else{
                   $use_count_no = $order['ticket_num']; //未使用的票数
                }
            }else{
                   $use_count_no = OrderGoods::where(['order_id' => $order_id, 'status' => 0])->count(); //未使用的票数
            }
            if ($use_count_no == $num) {
                //退款数量与未使用的票数相等，订单状态改为撤销
                $param = [
                    'order_status' => self::USE_STATUS_REVOKE, //撤销（退款）状态
                    'refund_mark'=> self::REFUND_MARK_YES, //全退标识
                ];
            } else {
                $param = [
                    'refund_mark'=> self::REFUND_MARK_PARTIAL,//部分退款标识
                ];
            }
        }
        $order->save($param);
        $orderLog->createLog($order_id, OrderLog::ORDER_REFUND, '订单退款');

        $voucher_no = $orderGoods->revokeOrder($order_id, $num); //更改订单项中商品状态，并返回凭证号
        if ($voucher_no) {
            $voucher->downState($order_id, $num); //更改凭证表中的凭证号状态
        }
    }




    /**
     * [recallRefund 撤销（退款）]
     * @Author   ZhouYunpeng
     * @DateTime 2020-12-30
     * @param    [type]      $order_id [description]
     * @param    [type]      $num      [description]
     * @return   [type]                [description]
     */
    public function recallRefund($order_id, $num)
    {
        $order = $this->with(['goods'])->where('order.id', $order_id)->find();
        if ($order) {
            $orderGoods = new OrderGoods();
            $voucher    = new Voucher();

            if ($order['goods']['refundPart']) {
                //整批退完
                $data = [
                    'refund_mark'  => self::REFUND_MARK_N0,
                    'order_status' => self::USE_STATUS_NO,
                ];
            } else {
                $result = $orderGoods->checkTicketNum($order_id, $num); //检验票的数量
                if ($result) {
                    $data = [
                        'refund_mark'  => self::REFUND_MARK_N0,
                        'order_status' => self::USE_STATUS_NO,
                    ];
                } else {
                    $data = [
                        'refund_mark'  => self::REFUND_MARK_PARTIAL,
                        'order_status' => self::USE_STATUS_NO,
                    ];
                }
            }
            try {
                
                $order->save($data);
                $orderGoods->recallRefund($order_id, $num);
                $voucher->changeState($order_id, $num);

            } catch (Exception $e) {
                \exception($e->getMessage());
            }
        }    

    }

    /***
     * @param array $data
     * @return false|int|mixed
     * 创建订单
     */
    public function add(array $data)
    {   
        Db::startTrans();
        try {
            $rest = $this->allowField(true)->save($data);
            $orderLog = new OrderLog();
            $orderLog->createLog($this->id, OrderLog::CREATE_ORDER, '创建订单');
            // $this->destock($this->id);
            $this->addTotalSales($data['goods_id'],$data['ticket_num'],$data['play_time']);
            //九如山
            // if ($data['scenic_id'] == 113) {
            //    $data['id'] = $this->id; 
            //    $this->jrsSend($data);
            // }
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            throw new Exception($e->getMessage());
        }
        return $rest;
    }



    /**
     * @param $user_id 购买用户id
     * @param $goods_id 商品id
     * @return bool
     * 用户购买规则限制
     */
    public function buyRule($user_id, $goods_id,$number = 0)
    {
        $where = [
            'user_id'      => $user_id,
            'goods_id'     => $goods_id,
            'order_status' => self::USE_STATUS_NO
        ];
        $goods = Goods::get(['id' => $goods_id]);

        $buy_times = $this->where($where)->count(); //此商品的购买次数
        //限制购买次数
        if ($goods['buy_times_num'] && $buy_times >= $goods['buy_times_num']) {
            throw new Exception('此商品仅限每位用户购买'.$goods['buy_times_num'].'次');
        }

        //单笔订单最高购买张数
        if ($goods['maximum'] && $number > $goods['maximum']){
            throw new Exception('单笔最高购买:'.$goods['maximum'].'张');
        }
        // $total = $this->where($where)->sum('ticket_num'); //累计购买量
        // $value = $goods['maximum'] - $total;
        // if ($number > $value){
        //     throw new Exception('此商品累计最高购买:'.$goods['maximum'].'张,您累计购买:'.$total.'张');
        // }
    }
    
    /**
     * [ticketNum 获取购票数量]
     * @Author   ZhouYunpeng
     * @DateTime 2021-05-27
     * @param    [type]      $user_id  [description]
     * @param    [type]      $goods_id [description]
     * @return   [type]                [description]
     */
    public function ticketNum($user_id, $goods_id)
    { 
      if ($user_id) {
            $where = ['user_id'=>$user_id,'goods_id'=>$goods_id];
      }else{
            $where = ['goods_id'=>$goods_id];
      }  
      $total = $this->where($where)->sum('ticket_num'); 
      return $total;
    }

    /**
     * [addTotalSales 增加总销量]
     * @Author   ZhouYunpeng
     * @DateTime 2021-04-27
     * @param    [type]      $goods_id [description]
     * @param    [type]      $sold_num [description]
     * @return   [type]                [description]
     */
    public  function addTotalSales($goods_id,$num,$time)
    {
        $goods  = Goods::get($goods_id);
        $scenic = Scenic::get($goods['scenic_id']);

        $goods->setInc('total_sales', $num);
        $scenic->setInc('total_sales', $num);
        if ($goods['is_virtual_sales']){
            $goods->setInc('virtual_sales',$num);
        }
        if ($goods['is_day_stock']) {
            $dayModel = new DayInventory();
            $day = $dayModel->get(['goods_id' => $goods_id,'day_time' => $time,'oneStock'=>['>',0]]);
            if ($day) {
                $day->setInc('already_sold',$num); 
            }
        }
    }
    
    /**
     * [subtractTotalSales 减少总销量]
     * @Author   ZhouYunpeng
     * @DateTime 2021-04-29
     * @return   [type]      [description]
     */
    public function subtractTotalSales($goods_id,$num,$time)
    {
        $goods  = Goods::get($goods_id);
        $scenic = Scenic::get($goods['scenic_id']);

        $goods->setDec('total_sales', $num);
        $scenic->setDec('total_sales', $num);
        if ($goods['is_virtual_sales']){
            $goods->setDec('virtual_sales',$num);
        }
        if ($goods['is_day_stock']) {
            $dayModel = new DayInventory();
            $day = $dayModel->get(['goods_id' => $goods_id,'day_time' => $time,'oneStock'=>['>',0]]);
            if ($day) {
                $day->setDec('already_sold',$num); 
            }
        }
    }





    /**
     * @param array $where
     * @return array|bool
     * 支付页数据
     */
    public function pay($where = [])
    {
        $resut = $this->with(['scenic', 'goods'])
            ->where($where)
            ->find();
        $scenic_image = explode(',', $resut['scenic']['scenic_images']);
        $data = [
            'buy_role'        => $resut['buy_role'],
            'timeout_express' => $this->exprieTime($resut['add_time'],$resut['is_confirm'],$resut['confirm_time']),
            'goods_title'     => $resut['product_name'],
            'scenic_image'    => reset($scenic_image),
            'amount'          => $resut['order_amount'],
            'price'           => $resut['goods_price'],
            'num'             => $resut['ticket_num'],
            'scenic_id'       => $resut['scenic_id'],
            'goods_id'        => $resut['goods_id'],
            'coupons_id'      => $resut['coupons_id'],
            'discount_amount' => $resut['discount_amount'],
            'real_amount'     => $resut['real_amount'],
            'order_id'        => $resut['id']
        ];

        if ($resut) {
            return $data;
        } else {
            return false;
        }
    }

    /**
     * @param $data
     * @return array
     * 店铺用户订单列表
     */
    public function getUserOrderList($data)
    {
        $where = [];
        $scenicModel = new Scenic();
        switch ($data['status']) {
            case 1: //待付款
                $where['pay_status'] = self::PAY_STATUS_NO;
                $where['order_status']  = self::USE_STATUS_NO;
                break;
            case 2: //待使用
                $where['pay_status']   = [['=', self::PAY_STATUS_YES], ['=', self::PAY_STATUS_PARTIAL_REFUND], 'or'];
                $where['order_status'] = [['=', self::USE_STATUS_NO], ['=', 6], 'or'];
                break;
            case 3: //待评价
                // $where['pay_status'] = self::PAY_STATUS_YES;
                $where['pay_status']   = [['=', self::PAY_STATUS_YES], ['=', self::PAY_STATUS_PARTIAL_REFUND], 'or'];
                $where['order_status'] = self::USE_STATUS;
                $where['is_comment'] = self::NO_COMMENT;
                break;
            case 4: //退款、售后
                $where['refund_mark'] = ['neq', self::REFUND_MARK_N0];
                $where['order_status']= ['neq', self::USE_STATUS];
        }
        if (!empty($data['user_id'])) {
            $where['user_id'] = $data['user_id'];
            $where['buy_role'] = $data['buy_role'];
        }
        $field = [
            'order.id',
            'play_time',
            'ticket_num',
            'buy_role',
            'user_id',
            'product_name',
            'goods_id',
            'scenic_id',
            'goods_price',
            'order_amount',
            'out_trade_no',
            'pay_status',
            'refund_mark',
            'order_status',
            'is_comment',
            'add_time',
            'rebook',
            'is_confirm',
            'confirm_time',
        ];
        $list = $this->where($where)
            ->with(['refund','scenic'])
            ->field($field)
            ->order('add_time desc')
            ->page($data['page'], 10)
            ->select();
        foreach ($list as $k => &$order) {
            $goods = Goods::withTrashed()->find(['id' => $order['goods_id']]);
            $order['scenicimage']     = $scenicModel->getPicture($order['scenic_id']);
            $order['timeout_express'] = $this->exprieTime($order['add_time'],$order['is_confirm'],$order['confirm_time']);
            $order['confirm_exprie_time'] = $this->confirmExprieTime($order['add_time'],$order['is_confirm']);
            $order['express_time']    = datetime($order['timeout_express']);
            $order['add_time']        = datetime($order['add_time']);
            $order['play_time']       = datetime($order['play_time'],'Y-m-d');
            $order['status']          = $this->getOrderStatus($order['pay_status'], $order['order_status'], $order['is_comment']);
            $order['is_refund']       = $goods['refundRules'] ? 1 : 0; //是否可退款
            $order['user_validation'] = $goods['user_validation'];
            $order['ticket_changing_status'] = $this->isTicketChanging($order,$goods['ticket_changing']) ? 1 :0;//是否可以改签
            $order->hidden(['pay_status','order_status','is_comment','rebook']);
        }
        return collection($list)->toArray();
    }
    protected function isTicketChanging($order = [],$ticket_changing)
    {
        if ($order['refund_mark'] || $order['rebook']){
            return false;
        }
        if ($order['pay_status'] != 1 || $order['order_status']){
            return false;
        }
        return $ticket_changing;
    }


    /**
     * [getOrderStatus 订单状态码转换]
     * @Author   ZhouYunpeng
     * @DateTime 2021-04-29
     */
    protected function getOrderStatus($pay, $order, $comment)
    {   
        $order_status = config('order');
        if ($pay == self::PAY_STATUS_NO) {
            //未付款
            if ($order == self::USE_STATUS_OFF) {
                //取消
                $status = $order_status['use'][$order];
            } else {
                //未付款
                $status = $order_status['pay'][$pay];
            }
            return $status;
        }elseif ($pay == self::PAY_STATUS_YES && $order == self::USE_STATUS) {
            if ($comment == self::NO_COMMENT) {
                $status = $order_status['comment'][$comment];
                return $status;
            }
        }elseif($pay == self::PAY_STATUS_PARTIAL_REFUND && $order == self::USE_STATUS) {
            if ($comment == self::NO_COMMENT) {
                $status = $order_status['comment'][$comment];
                return $status;
            }
        }elseif($pay == self::PAY_STATUS_YES && $order == 6){
            if ($comment == self::NO_COMMENT) {
                $status = $order_status['use'][0];
                return $status;
            }
        }

        $status = $order_status['use'][$order];
        return $status;
    }

    /**
     * @param $where
     * @return mixed
     * @throws Exception
     * 获取订单不同状态数量
     */
    public function getOrderStatusNum($where)
    {
        $status = explode(',', $where['status']);
        unset($where['status']);
        foreach ($status as $v) {
            switch ($v) {
                case 1: //待付款
                    $where['pay_status'] = self::PAY_STATUS_NO;
                    $where['order_status'] = self::USE_STATUS_NO;
                    $key = 'pay_count';
                    break;
                case 2: //待使用
                    $where['pay_status'] = self::PAY_STATUS_YES;
                    $where['order_status'] = self::USE_STATUS_NO;
                    $key = 'use_count';
                    break;
                case 3: //待评价
                    $where['pay_status'] = self::PAY_STATUS_YES;
                    $where['order_status'] = self::USE_STATUS;
                    $where['is_comment'] = self::NO_COMMENT;
                    $key = 'comment_count';
                    break;
                case 4: //退款
                    $where['refund_mark'] = [['=', self::REFUND_MARK_PARTIAL], ['=', self::REFUND_MARK_YES], 'or'];
                    $key = 'refund_count';
                    break;
            }
            $data[$key] = $this->where($where)->count();
        }
        return $data;
    }


    /**
     * [autoCancel 自动取消订单]
     * @Author   ZhouYunpeng
     * @DateTime 2021-04-29
     * @param    [type]      $timeout [description]
     */
    public function autoCancel($timeout)
    {
        $order_list = $this->where(['pay_status'=>self::PAY_STATUS_NO,'order_status' => self::USE_STATUS_NO,'create_time'=>date("Y-m-d")])->select();
        $order_list = collection($order_list)->toArray();
        $orderLog = new OrderLog();
        if (count($order_list) > 0) {
            Db::startTrans();
            try {
                foreach ($order_list as $k => $v) {
                    $expire_time = $v['add_time'] + $timeout * 60;//过期时间
                    if ($v['is_confirm'] == 1){
                        $expire_time = $this->exprieTime($v['add_time'],$v['is_confirm'],$v['confirm_time']);
                    }
                    //当前时间超过下单时间+支付过期分钟，该订单自动取消
                    if ($v['ticket_num'] && time() >= $expire_time){
                        $this->subtractTotalSales($v['goods_id'],$v['ticket_num'],$v['play_time']);
                        $rest =  $this->where(['id'=>$v['id']])->update(['order_status'=>self::USE_STATUS_OFF]); //更新订单
                        if ($rest){
                            $orderLog->createLog($v['id'], OrderLog::ORDER_CANCAL, '订单取消'); //订单操作记录
                        }
                    }
                }

                Db::commit();
            } catch (Exception $e) {
                Db::rollback();
                \exception($e->getMessage());
            }
        }
    }


    /**
     * [cancel 取消订单]
     * @Author   ZhouYunpeng
     * @DateTime 2021-04-29
     * @param    array       $where [description]
     * @return   [type]             [description]
     */
    public function cancel($where = [])
    {
        $where['pay_status']   = self::PAY_STATUS_NO;
        $where['order_status'] = self::USE_STATUS_NO;
        $order = self::get($where);
        $orderLog = new OrderLog();
        if ($order) {
            Db::startTrans();
            try {
                $order->order_status = self::USE_STATUS_OFF;
                $order->update_time  = time();
                $order->save();
                $this->subtractTotalSales($order->goods_id, $order->ticket_num,$order->play_time);
                $orderLog->createLog($order->id, OrderLog::ORDER_CANCAL, '订单取消');
                Db::commit();
            } catch (Exception $e) {
                Db::rollback();
            }

            return true;
        } else {
            return false;
        }
    }

    /**
     * [getOrderDetails 普通用户订单详情]
     * @Author   ZhouYunpeng
     * @DateTime 2020-07-17
     * @param    array       $where [description]
     * @return   [type]             [description]
     */
    public function getOrderDetails($order_id)
    {
        $field = [
            'id',
            'sell_id',
            'play_time',
            'play_time_notes',
            'ticket_num',
            'order_name',
            'order_phone',
            'store_id',
            'buy_role',
            'user_id',
            'product_name',
            'goods_id',
            'scenic_id',
            'goods_price',
            'order_amount',
            'out_trade_no',
            'pay_status',
            'order_status',
            'is_comment',
            'add_time',
            'pay_time',
            'refund_mark',
            'rebook',
            'is_confirm',
            'confirm_time',
            'assembling_place',
            'is_third',
            'discount_amount',
            'real_amount',
            'coupons_id'
        ];
        $orderLog = new OrderLog();
        $orders = self::with(['tourist', 'voucher', 'voucherlog', 'store'])->field($field)->find($order_id);
        if ($orders) {
            $goods  = Goods::withTrashed()->find(['id' => $orders['goods_id']]);
            $scenic = Scenic::get(['id' => $orders['scenic_id']]);

            //商家电话和名称
            $orders['store']['store_name'] = $scenic['scenic_name'];
            $orders['store']['phone'] = $scenic['scenic_tel'];
            $orders['store']['mobile'] = $scenic['scenic_tel'];

            //分销商店铺名称
            $distributor = \app\common\model\user\Distributor::get(['user_id'=>$orders['sell_id']]);
            $orders['shop_name'] = $distributor['name'];
         
            if ($orders['refund_mark'] !== 0) {
                //退款订单数量
                $orders['refund_count']   = Refund::where(['order_id' => $orders['id']])->count();
                $orders['refund_tickets'] = Refund::where(['order_id' => $orders['id'],'refund_status'=>[['=',0],['=',1],'or']])->sum('refund_num');
            }else{
                $orders['refund_count'] = 0;
                $orders['refund_tickets'] = 0;
            }
            $orders['order_log'] = $orderLog->getOrderLog($orders['id']); //订单变更记录
            $orders['play_time'] =  $orders['play_time_notes'] ?  $orders['play_time_notes'] : date('Y-m-d', $orders['play_time']);
            $orders['timeout_express'] = $this->exprieTime($orders['add_time'],$orders['is_confirm'],$orders['confirm_time']);
            $orders['confirm_exprie_time'] = $this->confirmExprieTime($orders['add_time'],$orders['is_confirm']);
            $orders['add_time'] = date('Y-m-d H:i:s', $orders['add_time']);
            $orders['pay_time'] = date('Y-m-d H:i:s', $orders['pay_time']);
            $orders['status'] = $this->getOrderStatus($orders['pay_status'], $orders['order_status'], $orders['is_comment']);
            //第三方产品未出票
            if ($orders['is_third']) {
                $order_goods = Db::name('order_goods')->where(['order_id'=>$orders['id']])->find();
                if ($order_goods) {
                    $orders['is_refund'] = $goods['refundRules'] ? 1 : 0; //是否可退款
                    $orders['take_ticket'] = 1;
                }else{
                    $orders['is_refund'] = 1; //未出票
                    $orders['take_ticket'] = 0;
                }
            }else{
                  $orders['is_refund'] = $goods['refundRules'] ? 1 : 0; //是否可退款 
                  $orders['take_ticket'] = 1;
            }
            $orders['goods_type_id'] = $goods['goods_type_id'];
            $orders['ticket_changing_status'] = $this->isTicketChanging($orders,$goods['ticket_changing']) ? 1 :0;//是否可以改签
            $orders['user_validation'] = $goods['user_validation'];
            if ($goods['user_validation']) {
                $orders['need_code'] = $goods['need_code'];
                $orders['validation_explain'] = SysConfig::get('site.validation_explain');
            }
            //幸运码
            if ($goods['lucky']) {
                $orders['lucky'] = 1;
                $lucky_number = Db::name('lucky_number')->where(['order_id'=>$orders['id']])->find();
                $orders['lucky_number'] = $lucky_number['number'];
                $lucky = Db::name('lucky')->where(['goods_id'=>$orders['goods_id']])->order('id desc')->find();
                if ($lucky) {
                    $orders['lucky_status'] = $lucky['status'];
                    $orders['lucky_title']  = $lucky['title'];
                    $orders['win_number']   = $lucky['win_number'];
                }
                
            }else{
                $orders['lucky'] = 0;
            }
            
            $orders['goods'] = $goods->goodsInfo($orders['goods_id']);
            $orders['scenic'] = [
                'id'           => $scenic['id'],
                'scenic_name'  => $scenic['scenic_name'],
                'ticket_check' => date('H:i', $goods['check_start_time']).'-'.date('H:i', $goods['check_end_time']).' '.$goods['check_time_notes'],
                'ticket_check_info' => $goods['parkCheck'] ? $goods['parkCheck'] : '无需换票,直接入园',
            ];
            $orders->hidden(['rebook']);

            //智游宝产品
            // if ($orders['is_third']) {
            //   $thirdparty_goods =  Db::name('thirdparty_goods')->where(['goods_id'=>$orders['goods_id']])->find();
            //   if ($thirdparty_goods['system_id'] == 3) {
            //      $orders['is_zyb'] = 1;
            //      $zybOrder = Db::name('third_zyb_order')->where(['order_id'=>$orders['id']])->find();
            //      $orders['zybCodeUrl'] = $zybOrder['codeURL'];
            //   }else{
            //      $orders['is_zyb'] = 0;
            //   }
            // }
            $orders['coupons_detail'] = [];
            if($orders['coupons_id']){
               $orders['coupons_detail'] = UsersMarketingCoupons::getUsersCouponsDetails($orders['coupons_id']);
            }
        }
        return $orders;
    }

    /**
     * @param array $where
     * 退款申请详情接口
     */
    public function refundDetails($where = [])
    {
        $field = [
            'order.id',
            'play_time',
            'ticket_num',
            'user_id',
            'product_name',
            'goods_id',
            'scenic_id',
            'goods_price',
            'order_amount',
            'real_amount',
            'coupons_id',
            'discount_amount',
            'out_trade_no',
            'buy_role',
        ];
        $scenicModel = new Scenic();
        $order = self::with(['scenic'])
                ->where($where)
                ->field($field)
                ->find();

        if ($order) {
            $remain_num = OrderGoods::where(['order_id' => $order['id'], 'status' => OrderGoods::STATUS_NO])->count();
            $map = ['id' => $order['goods_id']];
            $goods = Goods::get($map);
            $order['scenicimage'] = $scenicModel->getPicture($order['scenic_id']);
            $order['is_charge'] =  $goods['refundChargePlan']; //退款方案:0=无手续费,1=每笔订单收取手续费，2=每张门票收取手续费
            //有效期内
            if ($goods['refundTimeBar'] == 1) {
                    $now_time = time();
                    $day = $goods['refundTimeBarDay'];
                    $expiration_date = date('Y-m-d',strtotime("-$day day",$order['play_time']));
                    $refundTime = date('H:i', $goods['refundTimeBarTime']);
                    $expiry_time =strtotime($expiration_date.' '.$refundTime);
                    
                    if ($expiry_time > $now_time) {
                        //有效期前X天
                        if ($goods['refundChargePlan'] == 0) {
                            $order['charge'] = 0;
                        } elseif ($goods['refundChargePlan'] == 1) {
                            $order['charge'] = $goods['refundChargeMoney'];
                        } else {
                            $order['charge'] = $goods['refundChargeMoney'];
                        } 
                    }else{
                         $order['is_charge'] =  $goods['refundChargePlanAfter']; //退款方案:0=无手续费,1=每笔订单收取手续费，2=每张门票收取手续费
                        //有效期前天后
                        if ($goods['refundChargePlanAfter'] == 0) {
                            $order['charge'] = 0;
                        } elseif ($goods['refundChargePlanAfter'] == 1) {
                            $order['charge'] = $goods['refundChargeMoneyAfter'];
                        } else {
                            $order['charge'] = $goods['refundChargeMoneyAfter'];
                        } 
                    }
                 
            }else{
                $order['charge'] = $goods['refundRules'] ?  $goods['refundChargeMoney'] : 0; //手续费金额
            }
            // dump('66666');exit();
            //第三方未出票
            if ($order['is_third']) {
                $order_goods = Db::name('order_goods')->where(['order_id'=>$order['id']])->find();
                if ($order_goods) {
                    $order['is_refund_part'] = $goods['refundPart']; 
                    $order['remain_num'] = $remain_num; //剩余票数
                }else{
                     $order['is_refund_part'] = 1; 
                     $order['remain_num'] = $order['ticket_num']; //剩余票数
                }
            }else{
              $order['is_refund_part'] = $goods['refundPart'];
              $order['remain_num'] = $remain_num; //剩余票数  
            }    
            
            $order['reason'] = Db::name('refund_reason')->select(); //退款原因
        }
        return $order;
    }

    /*****
     * @param $order_id
     * @param bool $is_all
     * 更改订单使用状态 $is_all 未true 已使用 fales 部分使用
     */
    public function changeOrderUsageStatus($order_id, $is_all = false)
    {
        $order = self::get(['id' => $order_id]);
        $order_log = new OrderLog();
        if ($is_all) {
            //已使用
            $order->order_status = Order::USE_STATUS;
            $action_type         = OrderLog::ORDER_USE;
            $action_type_msg     = '订单全部已使用';
        } else {
            //部分使用
            $order->order_status = 6;
            $action_type         = OrderLog::ORDER_USE_PARTIAL;
            $action_type_msg     = '订单部分已使用';
        }

        $order->save();
        $order_log->createLog($order_id, $action_type, $action_type_msg);
    }


    /**
     * @param $goods_id
     * 订单过期操作
     */
    public function expired($goods_id)
    {
        $where = [
            'goods_id'      => ['in', $goods_id],
            'order_status'  => self::USE_STATUS_NO,
            'pay_status'    => self::PAY_STATUS_YES,
        ];
        $goods      = new Goods();
        $orderGoods = new OrderGoods();
        $voucher    = new Voucher();
        $orderLog   = new OrderLog();

        $order_list = $this->where($where)
                          ->select();
        try{
            foreach ($order_list as $order) {
                $result =  $goods->expire($order['goods_id'], $order['play_time']);
                if ($result) {
                    $params = [
                        'order_status' => self::USE_STATUS_EXPIRE,
                        'update_time' =>time()
                    ];
                    $orderLog->createLog($order['id'], OrderLog::ORDER_EXPIRE, '订单过期');
                    $order->save($params);
                    $orderGoods->expired($order['id']);//订单项过期
                    $voucher->expired($order['id']);//凭证号
                    $goods->expired_operation($order['goods_id'],$order['id']);//过期规则操作
                }
            }
        }catch (Exception $e){
            savelog('订单过期操作--model--',$e->getMessage());
        }

    }

    /**
     * @param $order_id 订单id
     * @param $user_id 购买商用户id 供应商或分销商id
     * @return false|int|true
     * 分销商余额支付
     */
    public function balancePay($order_id,$user_id)
    {
        $order = $this->get(['id' => $order_id]);

        //分销商余额支付
        $distributor  = User::get($user_id);
        $result = $distributor->money(-$order['order_amount'],$distributor['id'],$type = 1 ,'购买商品',$order_id,1,$order['ticket_num']);

        $param = [
            'pay_status' => self::PAY_STATUS_YES,
            'update_time' => time(),
            'pay_time'  => time(),
        ];
        $rest = $order->save($param);
        if ($result !== false && $rest !== false){
            Rebate::createRebate($order_id);
            $logModel = new OrderLog();
            $logModel->createLog( $order['id'], OrderLog::PAY_YES,'订单支付成功');
            return true;
        }else{
            return false;
        }

    }
    
    /**
     * [subtract 立减]
     * @Author   ZhouYunpeng
     * @DateTime 2022-01-19
     * @param    [type]      $params [description]
     */
    public function subtract($params,$amount,$user_id)
    {
        $allocationModel = new DistributionAllocation;
        $allocation = $allocationModel->get(['goods_id'=>$params['info']['goods_id']]);
        if ($allocation['num_restriction'] || $allocation['total_restriction']) {
            $ticket_total = $this->ticketNum(0,$params['info']['goods_id']);
            //总数量
            if ($allocation['total_restriction']) {
                if ($allocation['num_restriction']) {
                     $user_ticket = $this->ticketNum($user_id,$params['info']['goods_id']);
                     if (($user_ticket+$params['date']['num']) <= $allocation['num_restriction']){
                       $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                       return $amount;
                     }else{
                       return $amount;
                     }  
                 }else{
                     $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                     return $amount;
                 }
            }else{
                if ($allocation['num_restriction']) {
                     $user_ticket = $this->ticketNum($user_id,$params['info']['goods_id']);
                     if (($user_ticket+$params['date']['num']) <= $allocation['num_restriction']){
                       $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                       return $amount;
                     }else{
                       return $amount; 
                     }  
                 }else{
                     $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                     return $amount;
                 }
            }
        }else{
            $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
            return $amount;
        }
    }



    /**
     * @param int $order_id 订单 id
     * @param int $goods_id 商品id
     * @param $store_id
     * @return array
     * 改签数据
     */
    public function getChangDate(int $order_id, int $goods_id, $store_id)
    {
        $goods = Goods::get($goods_id);
        $order = $this->get($order_id);
        $salesModel = new Sales();
        $play_time = $order['play_time'];
        $rang = $goods['ticket_changing_range'];
        $start = strtotime("- $rang day", $play_time);
        $end = strtotime("+ $rang day", $play_time);
        $start = datetime($start, 'Y-n-j');
        $end = datetime($end, 'Y-n-j');
        $calendar = $salesModel->calendar($goods_id);


        //提前购买
        if ($goods['before'] == 2) {
            if ($goods['beforeDay']) {
                $day = $goods['beforeDay'];
                $start = date("Y-m-d",strtotime("+$day day"));
            }else{
                $start = date("Y-m-d");
            }  
            if (date('H:i', $goods['beforeTime']) < date('H:i', time())) {
                $start = date($start,strtotime("+1 day"));
                $start = date("Y-m-d",strtotime("+1 day",strtotime($start)));
            }
        }else{
            //验票结束
            if (date('H:i', $goods['check_end_time']) < date('H:i', time())) {
                $start = date($start,strtotime("+1 day"));
                if ($start > date('Y-m-d')) {
                   $start = date("Y-m-d");
                }
                $start = date("Y-m-d",strtotime("+1 day",strtotime($start)));
            }
        }

        $start_index = 0;
        $end_index = 0;
        foreach ($calendar as $key => $value) {
            if ($value['date'] == $start) {
                $start_index = $key;
            } elseif ($value['date'] <= $end) {
                $end_index = $key;
            }
        }

        foreach ($calendar as $key => $value) {
            if ($key >= $start_index && $key <= $end_index) {
                if (!$goods['ticket_changing_weekend']){
                    $date = strtotime($value['date']);
                    if (in_array(date('w',$date),[0,6])){
                        $value['one_stock'] = 0;
                    }
                }
                $data[] = $value;
            }
        }
        return $data;
    }

    /**
     * [jrsSend 九如山]
     * @Author   ZhouYunpeng
     * @DateTime 2022-01-26
     * @param    [type]      $order [description]
     * @param    [type]             [description]
     */
    private function jrsSend($order)
    {
        $Datetime = date('H');
        if ($Datetime >= 0 && $Datetime < 12) {
           $labels = '08:00-12:00';
        }else{
           $labels = '12:00-15:30';
        }
        $jrsDb =  Db::connect('jrs');
        $data  = [
            'scenic_id' => 10003,
            'admin_id'  => 2,
            'source'    => '济南九如山瀑布群风景区',
            'time'      => time(),
            'book_num'  => $order['ticket_num'],
            'lables'    => $labels,
            'days'      => date('Y-m-d',$order['play_time']),
            'order_id'  => $order['id']
        ];
        $jrsDb->name('scenic_time')->insert($data);

    }

    /***
     * @param int $order_time 订单创建时间戳
     * @param int $status 是否确认库存 0 需确认，1免确认或已确认 2供应商驳回
     * @param null $confirm_time 确认订单时间戳 null 未确认或免确认
     * @return float|int|null
     */
    private function exprieTime($order_time = 0,$status = 0,$confirm_time = null)
    {
       $timeout =  config('site.timeout_express');
       $timeout = $status ? $timeout : 30;
       if ($confirm_time && $status == 1){
           $timeout = 30;
           $order_time = $confirm_time;
       }
        $time = $order_time + $timeout * 60;
       return $time;
    }

    /***
     * @param $order_time 创建订单时间戳
     * @param int $status 是否确认库存 0 需确认，1免确认或已确认
     * @return float|int|null
     * 确认过期时间
     */
    private function confirmExprieTime($order_time = 0, $status = 0)
    {
        $time = $status ? null : $this->exprieTime($order_time,$status);
        return $time;
    }

    /**
     * [routeNotice 线路通知]
     * @Author   ZhouYunpeng
     * @DateTime 2021-12-30
     * @param    [type]      [description]
     */
    public function routeNotice($order)
    {
        $custodian = [
                 '0' =>['id' =>22,'openid' => 'o3Q6e1cU9CB1SJA9a-UO4M4d_0Rs'],
                 '1' =>['id' =>21,'openid' => 'o3Q6e1T509rX4uo89o8Nz36uin1s'],
                 '2' =>['id' =>57,'openid' => 'o3Q6e1ZXIfwkoKUpRdqaK0_kC9jI'],
                 '3' =>['id' =>89,'openid' => 'o3Q6e1Qh5cCvfBhEXmefI48t7l1k'],
                 '4' =>['id' =>806,'openid'=> 'o3Q6e1fmv_27IwbX--1PGYsYalOw'],
                 '5' =>['id' =>30,'openid' => 'o3Q6e1ZjD29IGxuwUGG9Zi6drs8I'],
                 // '6' =>['id' =>1,'openid'  => 'o3Q6e1TC0JvL-lNJ9dGGB8_ERpQA']
          ];
         foreach ($custodian as $key => $value) {
           $this->wechatNotice($value['openid'],$order,$pagepath = 0); 
         }
    }

    /**
     * [wechatNotice 微信通知]
     * @Author   ZhouYunpeng
     * @DateTime 2021-09-28
     * @return   [type]      [description]
     */
    public function wechatNotice($openid,$order,$pagepath)
    {    
         if ($pagepath) {
             $pagepath = 'pages/order/OrderInfo?orderId='.$order['id'].'&orderType=2';
             $remark   = ['请点击查看订单详情','#52627C'];
         }else{
             $pagepath = '';
             $remark   = ['姓名 : '.$order['order_name']."\n电话 : ".$order['order_phone']."\n出游时间 : ".date('Y-m-d',$order['play_time'])."\n乘车地点 : ".$order['assembling_place']."\n请注意查看新订单",'#52627C'];
         }
         $app = new Application(ConfigService::load());   
          //发送模板消息
         $app->notice->send([
                              'touser' => $openid,
                              'template_id' => 'sZh_6Z-T60XL7jBnTv8YjaHEHiOFz9C0HNrh-ctO07I',
                              // 'url' => 'http://www.store.liuyiqinzi.com/orderinfo/'.$order['id'].'/2',
                              'miniprogram'=>['appid'=>'wxab379d255ecd6df9',
                                              'pagepath'=>$pagepath
                                          ],
                              'data' => [
                                  'first' => ['订单提交成功','#52627C'],
                                  'keyword1' => [$order['product_name'],'#DB9728'],
                                  'keyword2' => [$order['id'],'#52627C'],
                                  'keyword3' => [$order['ticket_num'].'人','#52627C'],
                                  'keyword4' => ['￥'.$order['order_amount'],'#FF3030'],
                                  'remark'   => $remark,
                              ],
                          ]);
    }

    /**
     * @param $user_id 购买用户id
     * @param $goods_id 商品id
     * @return bool
     * 查询未付款订单信息（下单时间15分钟内）
     */
    public function getOrderByPayStatus($user_id, $goods_id, $number = 0)
    {
        $timeout = config('site.timeout_express');
        $msgData = null;
        $where = [
            'user_id'      => $user_id,
            'goods_id'     => $goods_id,
            'pay_status'   => self::PAY_STATUS_NO,
            'order_status' => self::USE_STATUS_NO
        ];
        $goods = Goods::get(['id' => $goods_id]);
        $buy_times = $this->where($where)->count(); //此商品未付款的订单数
        $order = $this->where($where)->find();
        $expire_time = $order['add_time'] + $timeout * 60;//过期时间
        if ($order['is_confirm'] == 1){
            $expire_time = $this->exprieTime($order['add_time'],$order['is_confirm'],$order['confirm_time']);
        }
        if($buy_times && time() < $expire_time) {
            $msgData['msg'] = "该商品存在待付款的订单，请前往订单列表中查看。";
            $msgData['order_id'] = $order['id'];
            $msgData['code'] = 4;
        }
        return $msgData;
    }

    /**
     * @param $user_id 购买用户id
     * @param $goods_id 商品id
     * @return bool
     * 查询未使用订单信息
     */
    public function getOrderByOrderStatus($user_id, $goods_id, $number = 0)
    {
        $msg = null;
        $where = [
            'user_id'      => $user_id,
            'goods_id'     => $goods_id,
            'order_status' => self::USE_STATUS_NO
        ];
        $goods = Goods::get(['id' => $goods_id]);
        $buy_times = $this->where($where)->count(); //此商品的购买次数
        //限制购买次数
        if ($goods['buy_times_num'] && $buy_times >= $goods['buy_times_num']) {
            $msg = '此商品仅限每位用户购买'.$goods['buy_times_num'].'次';
        }

        //单笔订单最高购买张数
        if ($goods['maximum'] && $number > $goods['maximum']){
            $msg = '单笔最高购买:'.$goods['maximum'].'张';
        }
        // $total = $this->where($where)->sum('ticket_num'); //累计购买量
        // $value = $goods['maximum'] - $total;
        // if ($number > $value){
        //     throw new Exception('此商品累计最高购买:'.$goods['maximum'].'张,您累计购买:'.$total.'张');
        // }
        return $msg;
    }
    
    /**
     * [subtractNew 立减]
     * @Author   Ming
     * @DateTime 2024-04-28
     * @param    [type]      $params [description]
     */
    public function subtractNew($params,$amount,$user_id)
    {
        $allocationModel = new DistributionAllocation;
        $allocation = $allocationModel->get(['goods_id'=>$params['info']['goods_id']]);
        if($allocation['num_restriction'] || $allocation['total_restriction']) {
            $totalTicket = $this->ticketNumNew(0,$params['info']['goods_id']);       //订单中总的购买数量
            $userTicket  = $this->ticketNumNew($user_id,$params['info']['goods_id']);//当前用户购买数量
            if($allocation['total_restriction']) {//限制总数量
                $partTicket = $allocation['total_restriction'] - $totalTicket;//剩余的总数量
                if($partTicket > 0) {
                    if($allocation['num_restriction']) {//限制每人的购买数量--购买次数少于限购
                        if($allocation['num_restriction'] > $userTicket) {
                            if(($params['date']['num'] + $userTicket) <= $allocation['num_restriction']) {
                                if($params['date']['num'] <= $partTicket) {
                                    $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                                }else {
                                    $amount = $amount - ($allocation['subtract_money']*$partTicket);
                                }
                            }else {
                                if($allocation['num_restriction'] <= ($partTicket + $userTicket)) {
                                    $amount = $amount - ($allocation['subtract_money']*($allocation['num_restriction'] - $userTicket));
                                }else {
                                    $amount = $amount - ($allocation['subtract_money']*$partTicket);
                                }
                            }
                        }
                    }else{
                        if($partTicket >= $params['date']['num']) {
                            $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                        }else {
                            $amount = $amount - ($allocation['subtract_money']*$partTicket);
                        }
                    }
                }
            }else{
                if($allocation['num_restriction']) {//限制每人的购买数量
                    if($userTicket < $allocation['num_restriction']){//购买次数少于限购
                        if($params['date']['num'] <= ($allocation['num_restriction'] - $userTicket)) {
                            $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                        }else {
                            $amount = $amount - ($allocation['subtract_money']*($allocation['num_restriction'] - $userTicket));
                        }
                    }
                }else{
                    $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
                }
            }
        }else{
            //购买数量和总数量都不限制
            $amount = $amount - ($allocation['subtract_money']*$params['date']['num']);
        }

        return $amount; 
    }

    
    /**
     * [ticketNumNew 获取购票数量]
     * @Author   Ming
     * @DateTime 2024-04-28
     * @param    [type]      $user_id  [description]
     * @param    [type]      $goods_id [description]
     * @return   [type]                [description]
     */
    public function ticketNumNew($user_id, $goods_id)
    { 
      if ($user_id) {
            $where = ['user_id'=>$user_id,'goods_id'=>$goods_id,'pay_status'=>self::PAY_STATUS_YES];
      }else{
            $where = ['goods_id'=>$goods_id,'pay_status'=>self::PAY_STATUS_YES];
      }  
      $total = $this->where($where)->sum('ticket_num');
      return $total;
    }
}
